package com.cbs.android.widget.countdownview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;

import com.cbs.android.widget.nospacetextview.NoSpaceTextView;

/**
 * Created by broche on 4/11/16.
 */
public class CountDownView extends NoSpaceTextView {
    private long deadLine = 0;
    private final MyHandler handler = new MyHandler();

    private String countDownTextFormat = "mm:ss.nnn";
    private String finalText = "";
    private int countDownTextColor = getCurrentTextColor();
    private int finalTextColor = getCurrentTextColor();
    private int countDownBackground;
    private int finalBackground;
    private long pauseTimeLeft = 0;
    private CountDownListener countDownListener = null;

    public CountDownView(Context context) {
        super(context);
    }

    public CountDownView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttrs(context, attrs);
    }

    public CountDownView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs);
    }

    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CountDownView);
        countDownTextFormat = typedArray.getString(R.styleable.CountDownView_countDownTextFormat);
        finalText = typedArray.getString(R.styleable.CountDownView_finalText);
        countDownTextColor = typedArray.getColor(R.styleable.CountDownView_countDownTextColor, getCurrentTextColor());
        finalTextColor = typedArray.getColor(R.styleable.CountDownView_finalTextColor, getCurrentTextColor());
        countDownBackground = typedArray.getResourceId(R.styleable.CountDownView_countDownBackground, -1);
        finalBackground = typedArray.getResourceId(R.styleable.CountDownView_finalBackground, -1);
        typedArray.recycle();
    }

    public void start(long period) {
        startTo(System.currentTimeMillis() + period, null);
    }

    public void start(long period, CountDownListener countDownListener) {
        startTo(System.currentTimeMillis() + period, countDownListener);
    }

    public void startTo(long deadLine) {
        startTo(deadLine, null);
    }

    public void startTo(long deadLine, CountDownListener countDownListener) {
        reset();
        long curTime = System.currentTimeMillis();
        this.deadLine = deadLine;
        setText(getText(curTime, deadLine));
        setTextColor(countDownTextColor);
        if (countDownBackground != -1) {
            setBackgroundResource(countDownBackground);
        } else {
            setBackgroundColor(Color.TRANSPARENT);
        }
        if (this.countDownListener != null) {
            this.countDownListener = null;
        }
        if (countDownListener != null) {
            this.countDownListener = countDownListener;
        }
        pauseTimeLeft = 0;
        Message message = handler.obtainMessage(0, this);
        handler.sendMessageDelayed(message, 30);
    }

    public void pause() {
        if (isStarted()) {
            if (isRunning()) {
                handler.removeMessages(0);
                pauseTimeLeft = deadLine - System.currentTimeMillis();
            }
        }
    }

    public void resume() {
        if (isStarted()) {
            if (!isRunning()) {
                deadLine = System.currentTimeMillis() + pauseTimeLeft;
                Message message = handler.obtainMessage(0, this);
                handler.sendMessageDelayed(message, 30);
            }
        }
    }

    public boolean isRunning() {
        return handler.hasMessages(0);
    }

    public boolean isStarted() {
        return !getText().equals(finalText);
    }

    public void stop() {
        handler.removeMessages(0);
        setText(finalText);
        setTextColor(finalTextColor);
        if (finalBackground != -1) {
            setBackgroundResource(finalBackground);
        } else {
            setBackgroundColor(Color.TRANSPARENT);
        }
        if (countDownListener != null) {
            countDownListener.onFinish(this);
            countDownListener = null;
        }
        pauseTimeLeft = 0;
    }

    public void reset() {
        handler.removeMessages(0);
        setText(finalText);
        setTextColor(finalTextColor);
        if (finalBackground != -1) {
            setBackgroundResource(finalBackground);
        } else {
            setBackgroundColor(Color.TRANSPARENT);
        }
        if (countDownListener != null) {
            countDownListener = null;
        }
        pauseTimeLeft = 0;
    }

    private void updateCountDownView() {
        long curTime = System.currentTimeMillis();
        setText(getText(curTime, deadLine));
        if (curTime > deadLine) {
            stop();
        }
    }

    private String getText(long curTime, long endTime) {
        long timeSpan = endTime - curTime;
        if (timeSpan < 0) {
            timeSpan = 0;
        }
        boolean needMinute = countDownTextFormat.contains("m");
        boolean needSecond = countDownTextFormat.contains("s");
        boolean needMSecond = countDownTextFormat.contains("n");

        int m = 0, s = 0, ms = 0;
        if (needMinute) {
            m = (int) (timeSpan / 1000 / 60);
            s = (int) ((timeSpan / 1000) % 60);
            ms = (int) (timeSpan % 1000);
        } else if (needSecond) {
            s = (int) (timeSpan / 1000);
            ms = (int) (timeSpan % 1000);
        } else if (needMSecond) {
            ms = (int) timeSpan;
        }

        StringBuilder stringBuilder = new StringBuilder();
        int minuteLen = 0;
        int secondLen = 0;
        int msecondLen = 0;
        for (int i = 0; i < countDownTextFormat.length(); i++) {
            char c = countDownTextFormat.charAt(i);
            if (c != 'm' && c != 's' && c != 'n') {
                if (minuteLen > 0) {
                    stringBuilder.append(String.format("%0" + minuteLen + "d", m));
                    minuteLen = 0;
                }
                if (secondLen > 0) {
                    stringBuilder.append(String.format("%0" + secondLen + "d", s));
                    secondLen = 0;
                }
                if (msecondLen > 0) {
                    stringBuilder.append(String.format("%0" + msecondLen + "d", ms));
                    msecondLen = 0;
                }
                stringBuilder.append(c);
            } else {
                if (c == 'm') {
                    minuteLen++;
                    if (secondLen > 0) {
                        stringBuilder.append(String.format("%0" + secondLen + "d", s));
                        secondLen = 0;
                    }
                    if (msecondLen > 0) {
                        stringBuilder.append(String.format("%0" + msecondLen + "d", ms));
                        msecondLen = 0;
                    }
                }
                if (c == 's') {
                    secondLen++;
                    if (minuteLen > 0) {
                        stringBuilder.append(String.format("%0" + minuteLen + "d", m));
                        minuteLen = 0;
                    }
                    if (msecondLen > 0) {
                        stringBuilder.append(String.format("%0" + msecondLen + "d", ms));
                        msecondLen = 0;
                    }
                }
                if (c == 'n') {
                    msecondLen++;
                    if (minuteLen > 0) {
                        stringBuilder.append(String.format("%0" + minuteLen + "d", m));
                        minuteLen = 0;
                    }
                    if (secondLen > 0) {
                        stringBuilder.append(String.format("%0" + secondLen + "d", s));
                        secondLen = 0;
                    }
                }
            }
        }
        if (minuteLen > 0) {
            stringBuilder.append(String.format("%0" + minuteLen + "d", m));
        }
        if (secondLen > 0) {
            stringBuilder.append(String.format("%0" + secondLen + "d", s));
        }
        if (msecondLen > 0) {
            stringBuilder.append(String.format("%0" + msecondLen + "d", ms));
        }

        return stringBuilder.toString();
    }

    private static class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            Message message = obtainMessage();
            message.copyFrom(msg);
            sendMessageDelayed(message, 30);
            CountDownView view = (CountDownView) msg.obj;
            view.updateCountDownView();
        }
    }

    public interface CountDownListener {
        void onFinish(CountDownView view);
    }
}
